From 70b4f633a6fbedb58c8b9134ac64ede854d489de Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
Date: Mon, 20 Nov 2023 12:27:46 +0100
Subject: refactor(components): replace PageLayout template with Page

* split pages in smaller components (it is both easier to maintain and
more readable, we avoid the use of fragments in pages directory)
* extract breadcrumbs from article tag (the navigation is not related
to the page contents)
* remove useReadingTime hook
* remove layout options except `isHome`
---
 src/pages/sujet/[slug].tsx | 153 +++++++++++++++++----------------------------
 1 file changed, 58 insertions(+), 95 deletions(-)

(limited to 'src/pages/sujet/[slug].tsx')

diff --git a/src/pages/sujet/[slug].tsx b/src/pages/sujet/[slug].tsx
index d9734a3..30adec3 100644
--- a/src/pages/sujet/[slug].tsx
+++ b/src/pages/sujet/[slug].tsx
@@ -10,11 +10,12 @@ import {
   getLayout,
   Heading,
   LinksWidget,
-  PageLayout,
   PostsList,
-  Time,
-  MetaList,
-  MetaItem,
+  Page,
+  PageHeader,
+  PageSidebar,
+  TocWidget,
+  PageBody,
 } from '../../components';
 import {
   getAllTopicsSlugs,
@@ -35,7 +36,7 @@ import {
   getWebPageSchema,
 } from '../../utils/helpers';
 import { loadTranslation, type Messages } from '../../utils/helpers/server';
-import { useBreadcrumb } from '../../utils/hooks';
+import { useBreadcrumb, useHeadingsTree } from '../../utils/hooks';
 
 export type TopicPageProps = {
   currentTopic: Topic;
@@ -61,6 +62,7 @@ const TopicPage: NextPageWithLayout<TopicPageProps> = ({
     title,
     url: `${ROUTES.TOPICS}/${slug}`,
   });
+  const { ref, tree } = useHeadingsTree({ fromLevel: 2 });
 
   const { asPath } = useRouter();
   const webpageSchema = getWebPageSchema({
@@ -101,9 +103,14 @@ const TopicPage: NextPageWithLayout<TopicPageProps> = ({
     </>
   );
   const pageUrl = `${CONFIG.url}${asPath}`;
+  const tocTitle = intl.formatMessage({
+    defaultMessage: 'Table of Contents',
+    description: 'PageLayout: table of contents title',
+    id: 'eys2uX',
+  });
 
   return (
-    <>
+    <Page breadcrumbs={breadcrumbItems}>
       <Head>
         <title>{seo.title}</title>
         {/*eslint-disable-next-line react/jsx-no-literals -- Name allowed */}
@@ -121,92 +128,29 @@ const TopicPage: NextPageWithLayout<TopicPageProps> = ({
         // eslint-disable-next-line react/no-danger -- Necessary for schema
         dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
       />
-      <PageLayout
-        breadcrumb={breadcrumbItems}
-        breadcrumbSchema={breadcrumbSchema}
-        title={getPageHeading()}
+      <Script
+        dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbSchema) }}
+        // eslint-disable-next-line react/jsx-no-literals -- Id allowed
+        id="schema-breadcrumb"
+        type="application/ld+json"
+      />
+      <PageHeader
+        heading={getPageHeading()}
         intro={intro}
-        headerMeta={
-          <MetaList>
-            <MetaItem
-              isInline
-              label={intl.formatMessage({
-                defaultMessage: 'Published on:',
-                description: 'Page: publication date label',
-                id: '4QbTDq',
-              })}
-              value={<Time date={dates.publication} />}
-            />
-            {dates.update ? (
-              <MetaItem
-                isInline
-                label={intl.formatMessage({
-                  defaultMessage: 'Updated on:',
-                  description: 'Page: update date label',
-                  id: 'Ez8Qim',
-                })}
-                value={<Time date={dates.update} />}
-              />
-            ) : null}
-            {officialWebsite ? (
-              <MetaItem
-                isInline
-                label={intl.formatMessage({
-                  defaultMessage: 'Official website:',
-                  description: 'TopicPage: official website label',
-                  id: 'zoifQd',
-                })}
-                value={officialWebsite}
-              />
-            ) : null}
-            {articles ? (
-              <MetaItem
-                isInline
-                label={intl.formatMessage({
-                  defaultMessage: 'Total:',
-                  description: 'ThematicPage: total label',
-                  id: 'lHkta9',
-                })}
-                value={intl.formatMessage(
-                  {
-                    defaultMessage:
-                      '{postsCount, plural, =0 {No articles} one {# article} other {# articles}}',
-                    description: 'ThematicPage: posts count meta',
-                    id: 'iv3Ex1',
-                  },
-                  { postsCount: articles.length }
-                )}
-              />
-            ) : null}
-          </MetaList>
-        }
-        widgets={
-          thematics
-            ? [
-                <LinksWidget
-                  heading={
-                    <Heading isFake level={3}>
-                      {thematicsListTitle}
-                    </Heading>
-                  }
-                  items={getLinksItemData(thematics)}
-                  // eslint-disable-next-line react/jsx-no-literals -- Key allowed
-                  key="related-thematics"
-                />,
-                <LinksWidget
-                  heading={
-                    <Heading isFake level={3}>
-                      {topicsListTitle}
-                    </Heading>
-                  }
-                  items={getLinksItemData(topics)}
-                  // eslint-disable-next-line react/jsx-no-literals -- Key allowed
-                  key="topics"
-                />,
-              ]
-            : []
-        }
-      >
+        meta={{
+          publicationDate: dates.publication,
+          total: articles?.length,
+          updateDate: dates.update,
+          website: officialWebsite,
+        }}
+      />
+      <PageSidebar>
+        <TocWidget
+          heading={<Heading level={3}>{tocTitle}</Heading>}
+          tree={tree}
+        />
+      </PageSidebar>
+      <PageBody className={styles.body} ref={ref}>
         {/*eslint-disable-next-line react/no-danger -- Necessary for content*/}
         {content ? <div dangerouslySetInnerHTML={{ __html: content }} /> : null}
         {articles ? (
@@ -229,13 +173,32 @@ const TopicPage: NextPageWithLayout<TopicPageProps> = ({
             />
           </>
         ) : null}
-      </PageLayout>
-    </>
+      </PageBody>
+      <PageSidebar>
+        {thematics ? (
+          <LinksWidget
+            heading={
+              <Heading isFake level={3}>
+                {thematicsListTitle}
+              </Heading>
+            }
+            items={getLinksItemData(thematics)}
+          />
+        ) : null}
+        <LinksWidget
+          heading={
+            <Heading isFake level={3}>
+              {topicsListTitle}
+            </Heading>
+          }
+          items={getLinksItemData(topics)}
+        />
+      </PageSidebar>
+    </Page>
   );
 };
 
-TopicPage.getLayout = (page) =>
-  getLayout(page, { useGrid: true, withExtraPadding: true });
+TopicPage.getLayout = (page) => getLayout(page);
 
 type TopicParams = {
   slug: string;
-- 
cgit v1.2.3

